#include "qAudioOutputWrapper.h"

#include <sstream>

#include <QDebug>
#include <QAudioOutput>
#include <QFile>
#include <QThread>

#include "qDebugWrapper.h"
#include "qAudioOutputEvent.h"

AudioOutput createAudioOutput(int frequency, int channels, int sampleSize)
{
    const char* codec = "audio/pcm";
    QAudioFormat::Endian byteOrder = QAudioFormat::LittleEndian;
    QAudioFormat::SampleType sampleType = QAudioFormat::SignedInt;

    QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());

    if (!info.supportedSampleRates().contains(frequency))
    {
        Q_PRINT("Error:: Selected frequency is not supported by qt backend!");
        return 0;
    }

    if (!info.supportedChannelCounts().contains(channels))
    {
        Q_PRINT("Error:: Selected channel count is not supported by qt backend!");
        return 0;
    }

    if (!info.supportedSampleSizes().contains(sampleSize))
    {
        Q_PRINT("Selected sample size is not supported by qt backend!");
        return 0;
    }

    if (!info.supportedCodecs().contains(codec))
    {
        Q_PRINT("Error:: Selected codec is not supported by qt backend!");
        return 0;
    }

    if (!info.supportedByteOrders().contains(byteOrder))
    {
        Q_PRINT("Error:: Selected byte order is not supported by qt backend!");
        return 0;
    }

    if (!info.supportedSampleTypes().contains(sampleType))
    {
        Q_PRINT("Error:: Selected sample type is not supported by qt backend!");
        return 0;
    }

    QAudioFormat qAudioFormat;

    qAudioFormat.setSampleRate(frequency);
    qAudioFormat.setChannelCount(channels);
    qAudioFormat.setSampleSize(sampleSize);
    qAudioFormat.setCodec(codec);
    qAudioFormat.setByteOrder(byteOrder);
    qAudioFormat.setSampleType(sampleType);

    if (!info.isFormatSupported(qAudioFormat))
    {
        Q_PRINT("Error:: Selected format not supported by qt backend!");
        return 0;
    }

    QAudioOutput* qAudioOutput = new QAudioOutput(qAudioFormat);

    qAudioOutput->setBufferSize(4096 * 4);

    return (void*)qAudioOutput;
}

AudioBuffer startAudioOutput(AudioOutput audioOutput)
{
    Q_ASSERT(audioOutput);

    QAudioOutput* qAudioOutput = (QAudioOutput*)audioOutput;

    if (qAudioOutput->state() != QAudio::StoppedState)
    {
        Q_PRINT("Error:: Invalid State!");
        return 0;
    }

    //AudioOutputEvent* event = new AudioOutputEvent();

    //if (!event->connect(qAudioOutput, SIGNAL(stateChanged(QAudio::State)), SLOT(onStateChanged(QAudio::State))))
    //{
    //    return 0;
    //}

    QIODevice* io = qAudioOutput->start();

    return (void*)io;
}

int isAudioOutputReady(AudioOutput audioOutput)
{
    Q_ASSERT(audioOutput);

    QAudioOutput* qAudioOutput = (QAudioOutput*)audioOutput;

    QAudio::State state = qAudioOutput->state();

    return state == QAudio::IdleState || state == QAudio::ActiveState;
}

int getAudioBufferFreeSize(AudioOutput audioOutput)
{
    Q_ASSERT(audioOutput);

    QAudioOutput* qAudioOutput = (QAudioOutput*)audioOutput;

    return qAudioOutput->bytesFree();
}

int getAudioBufferPeriodSize(AudioOutput audioOutput)
{
    Q_ASSERT(audioOutput);

    QAudioOutput* qAudioOutput = (QAudioOutput*)audioOutput;

    return qAudioOutput->periodSize();
}

void writeAudioBuffer(AudioBuffer audioBuffer, const char* data, int bufferSizeInBytes)
{    
    Q_ASSERT(audioBuffer);

    QIODevice* qIO = (QIODevice*)audioBuffer;

    qIO->write(data, bufferSizeInBytes);
}

void stopAudioOutput(AudioOutput audioOutput)
{
    Q_ASSERT(audioOutput);

    QAudioOutput* qAudioOutput = (QAudioOutput*)audioOutput;

    qAudioOutput->stop();
}

void destroyAudioOutput(AudioOutput audioOutput)
{
    Q_ASSERT(audioOutput);

    QAudioOutput* qAudioOutput = (QAudioOutput*)audioOutput;

    delete qAudioOutput;
}
